/**
 * 
 */
package com.example.demo.util;

import org.apache.commons.lang3.StringEscapeUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类, 继承org.apache.commons.lang3.StringUtils类
 * @author ThinkGem
 * @version 2013-05-22
 */
public class StringUtils extends org.apache.commons.lang3.StringUtils {

	private static Logger logger = LoggerFactory.getLogger(StringUtils.class);
    private static final char SEPARATOR = '_';
    private static final String CHARSET_NAME = "UTF-8";
    private static final Pattern FIND_TOPIC_TITLE = Pattern.compile("#[^#]*[0-9a-zA-Z\\u4e00-\\u9fa5]+[^#]*#");
    
    private static final Pattern FIND_ATUSER_TITLE = Pattern.compile("@[^@]+\b"); //at@ 功能
    /**
     * 转换为字节数组
     * @param str
     * @return
     */
    public static byte[] getBytes(String str){
    	if (str != null){
    		try {
				return str.getBytes(CHARSET_NAME);
			} catch (UnsupportedEncodingException e) {
				return null;
			}
    	}else{
    		return null;
    	}
    }
    
    /**
     * 转换为字节数组
     * @return
     */
    public static String toString(byte[] bytes){
    	try {
			return new String(bytes, CHARSET_NAME);
		} catch (UnsupportedEncodingException e) {
			return EMPTY;
		}
    }
    
    /**
     * 是否包含字符串
     * @param str 验证字符串
     * @param strs 字符串组
     * @return 包含返回true
     */
    public static boolean inString(String str, String... strs){
    	if (str != null){
        	for (String s : strs){
        		if (str.equals(trim(s))){
        			return true;
        		}
        	}
    	}
    	return false;
    }
    
	/**
	 * 替换掉HTML标签方法
	 */
	public static String replaceHtml(String html) {
		if (isBlank(html)){
			return "";
		}
		String regEx = "<.+?>";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(html);
		String s = m.replaceAll("");
		return s;
	}
	
	/**
	 * 替换为手机识别的HTML，去掉样式及属性，保留回车。
	 * @param html
	 * @return
	 */
	public static String replaceMobileHtml(String html){
		if (html == null){
			return "";
		}
		return html.replaceAll("<([a-z]+?)\\s+?.*?>", "<$1>");
	}
	

	/**
	 * 缩略字符串（不区分中英文字符）
	 * @param str 目标字符串
	 * @param length 截取长度
	 * @return
	 */
	public static String abbr(String str, int length) {
		if (str == null) {
			return "";
		}
		try {
			StringBuilder sb = new StringBuilder();
			int currentLength = 0;
			for (char c : replaceHtml(StringEscapeUtils.unescapeHtml4(str)).toCharArray()) {
				currentLength += String.valueOf(c).getBytes("GBK").length;
				if (currentLength <= length - 3) {
					sb.append(c);
				} else {
					sb.append("...");
					break;
				}
			}
			return sb.toString();
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(),e);
		}
		return "";
	}
	

	/**
	 * 转换为Double类型
	 */
	public static Double toDouble(Object val){
		if (val == null){
			return 0D;
		}
		try {
			return Double.valueOf(trim(val.toString()));
		} catch (Exception e) {
			return 0D;
		}
	}

	/**
	 * 转换为Float类型
	 */
	public static Float toFloat(Object val){
		return toDouble(val).floatValue();
	}

	/**
	 * 转换为Long类型
	 */
	public static Long toLong(Object val){
		return toDouble(val).longValue();
	}

	/**
	 * 转换为Integer类型
	 */
	public static Integer toInteger(Object val){
		return toLong(val).intValue();
	}
	
	/**
	 * 获得用户远程地址
	 */
	public static String getRemoteAddr(HttpServletRequest request){
		  String ip = request.getHeader("X-Forwarded-For");
		if ((ip == null) || (ip.length() == 0)|| ("unknown".equalsIgnoreCase(ip))) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if ((ip == null) || (ip.length() == 0)|| ("unknown".equalsIgnoreCase(ip))) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if ((ip == null) || (ip.length() == 0)|| ("unknown".equalsIgnoreCase(ip))) {
			ip = request.getRemoteAddr();
		}
		 //对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割  
        if(ip!=null && ip.length()>15){ //"***.***.***.***".length() = 15  
            if(ip.indexOf(",")>0){  
            	ip = ip.substring(0,ip.indexOf(","));  
            }  
        }  
		return ip != null ? ip : request.getRemoteAddr();
//		String remoteAddr = request.getHeader("X-Real-IP");
//        if (isNotBlank(remoteAddr)) {
//        	remoteAddr = request.getHeader("X-Forwarded-For");
//        }else if (isNotBlank(remoteAddr)) {
//        	remoteAddr = request.getHeader("Proxy-Client-IP");
//        }else if (isNotBlank(remoteAddr)) {
//        	remoteAddr = request.getHeader("WL-Proxy-Client-IP");
//        }
//        return remoteAddr != null ? remoteAddr : request.getRemoteAddr();
	}

	/**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld" 
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toCamelCase(String s) {
        if (s == null) {
            return null;
        }

        s = s.toLowerCase();

        StringBuilder sb = new StringBuilder(s.length());
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            if (c == SEPARATOR) {
                upperCase = true;
            } else if (upperCase) {
                sb.append(Character.toUpperCase(c));
                upperCase = false;
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }

    /**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld" 
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toCapitalizeCamelCase(String s) {
        if (s == null) {
            return null;
        }
        s = toCamelCase(s);
        return s.substring(0, 1).toUpperCase() + s.substring(1);
    }
    
    /**
	 * 驼峰命名法工具
	 * @return
	 * 		toCamelCase("hello_world") == "helloWorld" 
	 * 		toCapitalizeCamelCase("hello_world") == "HelloWorld"
	 * 		toUnderScoreCase("helloWorld") = "hello_world"
	 */
    public static String toUnderScoreCase(String s) {
        if (s == null) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        boolean upperCase = false;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);

            boolean nextUpperCase = true;

            if (i < (s.length() - 1)) {
                nextUpperCase = Character.isUpperCase(s.charAt(i + 1));
            }

            if ((i > 0) && Character.isUpperCase(c)) {
                if (!upperCase || !nextUpperCase) {
                    sb.append(SEPARATOR);
                }
                upperCase = true;
            } else {
                upperCase = false;
            }

            sb.append(Character.toLowerCase(c));
        }

        return sb.toString();
    }
    
    /**
     * 如果不为空，则设置值
     * @param target
     * @param source
     */
    public static void setValueIfNotBlank(String target, String source) {
		if (isNotBlank(source)){
			target = source;
		}
	}
 
    /**
     * 转换为JS获取对象值，生成三目运算返回结果
     * @param objectString 对象串
     *   例如：row.user.id
     *   返回：!row?'':!row.user?'':!row.user.id?'':row.user.id
     */
    public static String jsGetVal(String objectString){
    	StringBuilder result = new StringBuilder();
    	StringBuilder val = new StringBuilder();
    	String[] vals = split(objectString, ".");
    	for (int i=0; i<vals.length; i++){
    		val.append("." + vals[i]);
    		result.append("!"+(val.substring(1))+"?'':");
    	}
    	result.append(val.substring(1));
    	return result.toString();
    }
    
    public static boolean pattern(String reg, String msg)
    {
    	
    	return Pattern.compile(reg).matcher(msg).find();
    }
    
    public static boolean isEmpty(String str){
    	if (str == null || str.length() == 0) {
			return true;
		}
    	return false;
    }
    
    /**
     * 
     * combinationKey:根据查询维度组合key
     * @param key key的前缀
     * @param separator  分隔符
     * @param dimensionSets  不同的维度,格式为 Set<String>
     * @return 组合后的key
     * @since JDK 1.7
     */
    @SuppressWarnings("unchecked")
	public static Set<String> combinationKey(String key, String separator, Set<String>... dimensionSets){
 	   Set<String> resSet = new HashSet<String>();
 	   resSet.add(key);
 		for(Set<String> dimensionSet : dimensionSets){
 			resSet = buildKey(resSet, dimensionSet, separator);
 		}
 		return resSet;
 	}
    /**
     * 
     * buildKey: 循环调用生成key的方法
     * @param keySet 此维度之前组成的所有的key
     * @param dimensionSet  需要添加的当前的维度
     * @param separator 分隔符
     * @return  当前维度之前所有维度组成的key
     * @since JDK 1.7
     */
 	public static Set<String> buildKey(Set<String> keySet, Set<String> dimensionSet, String separator){
 		Set<String> resSet = new HashSet<String>();
 		for(String key : keySet){
 			for(String dimension : dimensionSet){
 				resSet.add(key+separator+dimension);
 			}
 		}
 		return resSet;
 	}

 	/**
 	 * 
 	 * strConvertMap:字符串转为map
 	 * @param str
 	 * @param separator 字符串的分隔符
 	 * @return
 	 * @since JDK 1.7
 	 */
 	public static Map<String,String> strConvertMap(String str, String separator){
 		Map<String,String> map = new HashMap<String, String>();
 		if(StringUtils.isEmpty(str)){
 			return map;
 		}
 		String[] strArr = str.split(separator);
 		for(String strA : strArr){
 			map.put(strA, strA);
 		}
 		return map;
 	}  
 	
 	/**
 	 * 
 	 * getLongListFormStr:字符串转Long类型list. <br/>
 	 * @author wangyinan
 	 * Date:2017年4月22日下午3:35:24
 	 * @param str
 	 * @return
 	 */
 	public static List<Long> getLongListFormStr(String str){
		if(StringUtils.isEmpty(str)) return null;
		String[] teaidary =  str.split(",");
		List<Long> list = new ArrayList<Long>();
		for(String item : teaidary){
			list.add(Long.valueOf(item));
		}
		return list;
	}
	
 	/**
 	 * getIntegerListFormStr:字符串转Integer类型list. <br/>
 	 * @author wangyinan
 	 * Date:2017年4月22日下午3:35:43
 	 * @param str
 	 * @return
 	 */
	public static List<Integer> getIntegerListFormStr(String str){
		if(StringUtils.isEmpty(str)) return null;
		String[] teaidary =  str.split(",");
		List<Integer> list = new ArrayList<Integer>();
		for(String item : teaidary){
			list.add(Integer.valueOf(item));
		}
		return list;
	}
	/**
	 * 转义符获得html标签字符串
	 * 
	 * @param str
	 * @return
	 */
	public static String getHtmlFormEscapeSquence(String str) {
		if (str == null)
			return "";
		str = str.replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"")
				.replaceAll("&nbsp;", " ").replaceAll("&copy;", "©").replaceAll("&reg;", "®").replaceAll("&apos;", "'");
		return str;
	}
	/**
	 * 中文乱码转化
	 */
	public static String getByteToString(String param) {
		try {
			if(!StringUtils.isEmpty(param)){
				String charset = "iso-8859-1";
				if (param.equals(new String(param.getBytes("iso-8859-1"), "iso-8859-1"))) {
					charset = "iso-8859-1";
				} else if (param.equals(new String(param.getBytes("gbk"), "iso-8859-1"))) {
					charset = "gbk";
				} else if (param.equals(new String(param.getBytes("utf8"), "iso-8859-1"))) {
					charset = "utf8";
				} else {
					return param;
				}
				byte[] b = param.getBytes(charset);
				return new String(b, "UTF-8");
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "";
	}
	public static void main(String[] args) {
		System.out.println(abbr("<p>家居安静</p><p><img src='http://t.cn/RKEbQ5L' title='1500438714736b049c45f-0d1f-48ea-8781-6fd2712c405c.jpg' alt='1500438714736b049c45f-0d1f-48ea-8781-6fd2712c405c.jpg'/></p>", 200));
	}
	
	/**
	 * removeSymbolAndExpression:(去除各种符号以及表情). <br/>
	 * @author jackl
	 * Date:2017年12月22日下午4:27:18
	 * @param content
	 * @return
	 */
	public static String removeSymbolAndExpression(String content){
		String contentNew="";
		try {
			content=content.replaceAll("[\\ud800\\udc00-\\udbff\\udfff\\ud800-\\udfff]", "");
			char[] chars = content.toCharArray();
			for(int i = 0; i < chars.length; i ++) {  
				if((chars[i] >= 19968 && chars[i] <= 40869) || (chars[i] >= 97 && chars[i] <= 122) || (chars[i] >= 65 && chars[i] <= 90)) {  
					contentNew=contentNew+chars[i];
				}  
			}  
		} catch (Exception e) {
		}
		return contentNew;
	}
	
	/**
	 * getTimesOfTime:(< 获取转换音频时长>).
	 *
	 * @author yanglu
	 * Date:2017年11月25日 下午6:38:04
	 * @param time
	 * @return：List<Integer>
	 */
	public static int getTimesOfTime(String time){
		if(StringUtils.isEmpty(time)){
			return 0;
		}
		String[] times = time.split(":");
		int dateTime = 0;
		if(times.length>1){
			dateTime = Integer.parseInt(times[0])*60+ Integer.parseInt(times[1]);
		}
		return dateTime;
	}
	
	public static List<String> getTopicListByContent(String content){
		List<String> topicList = new ArrayList<String>();
		if (!StringUtils.isEmpty(content)) {
			Matcher matcher = FIND_TOPIC_TITLE.matcher(content);
			while(matcher.find()) {
				String string = matcher.group()/*.replaceAll("#", "")*/;
				if(!topicList.contains(string)){
					topicList.add(string);
				}
			}
		}
		return topicList;
	}
	
	
	/**
	 * countChinese:统计汉字字符数量. <br/>
	 * @author lizhijun maolulee@163.com
	 * Date:2018年5月4日下午5:56:42
	 * @param str
	 * @return
	 */
	public static int countChinese(String str) {  
        int count = 0;  
        Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");  
        Matcher m = p.matcher(str);  
        while(m.find()){  
            count++;  
        }  
        return count;  
    }
	
	
	/**
	 * handleStoryContent:去除换行符，替换中文井号，替换话题内容的中文空格为英文空格，去除话题开始井号后以及结束井号前的一个或多个连续空格，替换话题内多个空格为单个. <br/>
	 * @author lizhijun maolulee@163.com
	 * Date:2018年2月26日下午12:21:08
	 * @param content
	 * @return
	 */
	public static String handleStoryContent(String content){
		if(!isEmpty(content)){
			content = content.replaceAll("\\n|\\r", ""); // 替换换行
			content = content.replaceAll("＃", "#"); // 替换中文井号
			Matcher matcher = FIND_TOPIC_TITLE.matcher(content);
			while(matcher.find()) {
				String groupStr = matcher.group();
				String handleStr = groupStr.replaceAll("　", " ");// 替换中文井号空格
				handleStr = handleStr.replaceAll("(#[ 　]*)|([ 　]*#)", "#");// 去除话题井号内靠近井号的空格
				handleStr = handleStr.replaceAll("( |　){2,}", " "); // 替换话题内多个空格
				content = content.replace(groupStr, handleStr);
			}
		}
		return content;
	}
	
	public static String handleNick(String userNick){
		if(!isEmpty(userNick)){
			userNick = userNick.replace("\\n|\\r", ""); // 替换换行
			userNick = userNick.replace("＃", "#"); // 替换中文井号
			userNick = userNick.replace("　", " ");// 替换中文井号空格
			userNick = userNick.replace("@", "");// 替换@
		}
		return userNick;
	}
	
	public static List<String> getAtUsertByContent(String content){
		List<String> atUserList = new ArrayList<String>();
		if (!StringUtils.isEmpty(content)) {
			Matcher matcher = FIND_ATUSER_TITLE.matcher(content);
			while(matcher.find()) {
				String string = matcher.group()/*.replaceAll("#", "")*/;
				if(!atUserList.contains(string)){
					atUserList.add(string);
				}
			}
		}
		return atUserList;
	}
	private static final char HEX_DIGITS[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };  
	  
	private static String toHexString(byte[] b) {  
	    StringBuilder sb = new StringBuilder(b.length * 2);  
	    for (int i = 0; i < b.length; i++) {  
	        sb.append(HEX_DIGITS[(b[i] & 0xf0) >>> 4]);  
	        sb.append(HEX_DIGITS[b[i] & 0x0f]);  
	    }  
	    return sb.toString();  
	}  
	  
	public static String Bit32(String SourceString) throws Exception {  
	    MessageDigest digest = MessageDigest.getInstance("MD5");  
	    digest.update(SourceString.getBytes());  
	    byte messageDigest[] = digest.digest();  
	    return toHexString(messageDigest);  
	}  
	  
	public static String Bit16(String SourceString) throws Exception {  
	    return Bit32(SourceString).substring(8, 24);  
	}
	
	public static List<String> parseStringToStrList(String str, String separator) {
		if (StringUtils.isEmpty(str)) {
			return null;
		}
		str = toBanJiao(str);
		List<String> list = new ArrayList<String>();
		try {
			String[] strArr = str.split(separator);
			for (int index = 0; index < strArr.length; index++) {
				list.add(strArr[index]);
			}
			return list;
		} catch (Exception e) {
			logger.error("解析错误!!", e);
		}
		return list;
	}
	
	/**
	 * 转半角 : 全角空格为12288，半角空格为32 其他字符半角(33-126)与全角(65281-65374)的对应关系是：均相差65248
	 * 
	 * @param input
	 * @return 半角化的字符
	 */
	public static String toBanJiao(String input) {
		char[] c = input.toCharArray();
		for (int i = 0; i < c.length; i++) {
			if (c[i] == 12288) {
				c[i] = (char) 32;
				continue;
			}
			if (c[i] > 65280 && c[i] < 65375)
				c[i] = (char) (c[i] - 65248);
		}
		return new String(c);
	}
	
	private static char[] numbersAndLetters = ("0123456789abcdefghijklmnopqrstuvwxyz" +
            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray();

	public static final String randomString(int length) {
	     if (length < 1) {
	         return null;
	     }
		 Random randGen = new Random();
	     char [] randBuffer = new char[length];
	     for (int i=0; i<randBuffer.length; i++) {
	         randBuffer[i] = numbersAndLetters[randGen.nextInt(71)];
	     }
	     return new String(randBuffer);
	}
	

    private static int min(int one, int two, int three)
    {
        return (one = one < two ? one : two) < three ? one : three;
    }

    /**
     * 获取两字符串的相似度
     */

    public static float getSimilarityRatio(String str, String target)
    {
        return 1 - (float) compare(str, target) / Math.max(str.length(), target.length());
    }

	public static boolean isPhone(String phone) {
		String regex = "^((13[0-9])|(14[5,7,9])|(15([0-3]|[5-9]))|(166)|(17[0,1,3,5,6,7,8])|(18[0-9])|(19[8|9]))\\d{8}$";
		if (phone.length() != 11) {
			return false;
		} else {
			Pattern p = Pattern.compile(regex);
			Matcher m = p.matcher(phone);
			boolean isMatch = m.matches();
			return isMatch;
		}
	}


    /***************************************************************************************/

	/**
	 * 全局数组,用于base64
	 */
	private static final String[] _strDigits = { "0", "1", "2", "3", "4", "5",
			"6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };

	/**
	 * MD5编码算法
	 *
	 * @param sourceStr 待计算的字符串
	 * @return String md5值
	 */
	public static String MD5Encode(String sourceStr) {
		String signStr=null;
		try {
			byte[] bytes = sourceStr.getBytes("utf-8");
			MessageDigest md5 = MessageDigest.getInstance("MD5");
			md5.update(bytes);
			byte[] md5Byte = md5.digest();
			if (md5Byte != null) {
				signStr = _byteToString( md5Byte);
			}
		} catch (NoSuchAlgorithmException e) {
		} catch (UnsupportedEncodingException e) {
		}
		return signStr;
	}

	/**
	 * 转换字节数组为16进制字串
	 */
	private static String _byteToString(byte[] bByte) {
		StringBuffer sBuffer = new StringBuffer();
		for (int i = 0; i < bByte.length; i++) {
			sBuffer.append(_byteToArrayString(bByte[i]));
		}
		return sBuffer.toString();
	}

	/**
	 * 返回形式为数字跟字符串
	 */
	private static String _byteToArrayString(byte bByte) {
		int iRet = bByte;
		if (iRet < 0) {
			iRet += 256;
		}
		int iD1 = iRet / 16;
		int iD2 = iRet % 16;
		return _strDigits[iD1] + _strDigits[iD2];
	}
}
